package com.keqiang.chart.impl.pie

import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.IntDef
import androidx.annotation.Px
import com.keqiang.chart.model.Entity
import com.keqiang.chart.utils.px

/**
 * 饼状图基础数据
 *
 * @author Created by wanggaowan on 2022/8/3 13:44
 */
open class BasePieEntity(value: Float = 0f) : Entity(value) {

    var color: Int = Color.GREEN

    /**
     * 是否绘制标签
     */
    var drawLabel: Boolean = false

    /**
     * 标签
     */
    var label: String? = null

    /**
     * 标签字体大小
     */
    @setparam:Px
    var labelSize: Float = 24f.px

    /**
     * 标签字体颜色
     */
    var labelColor: Int = Color.BLACK

    /**
     * 在[BasePieChart.radius]补充半径
     */
    @setparam:Px
    var addedRadius: Float = 0f

    /**
     * 绘制的起始角度
     *
     * 绘制时自动赋值，非自定义绘制不要修改此值
     */
    var drawStartAngle: Float = 0f

    /**
     * 绘制的结束角度
     *
     * 绘制时自动赋值，非自定义绘制不要修改此值
     */
    var drawSweepAngle: Float = 0F

    /**
     * 绘制的半径
     *
     * 绘制时自动赋值，非自定义绘制不要修改此值
     */
    var drawRadius: Float = 0f

    /**
     * 相比于圆心x轴坐标偏移距离
     *
     * 绘制时自动赋值，非自定义绘制不要修改此值
     */
    var offsetDx: Float = 0f

    /**
     * 相比于圆心y轴坐标偏移距离
     *
     * 绘制时自动赋值，非自定义绘制不要修改此值
     */
    var offsetDy: Float = 0f
}

/**
 * 标签在垂直方向的绘制位置
 * @author Created by wanggaowan on 2022/8/5 11:42
 */
@IntDef(LabelGravity.END, LabelGravity.TOP, LabelGravity.BOTTOM)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD)
@Retention(AnnotationRetention.SOURCE)
annotation class LabelGravity {
    companion object {
        /**
         * 绘制到线条尾部，垂直方向上字体中间和线条持平
         */
        const val END = 0

        /**
         * 绘制到线条上面
         */
        const val TOP = 1

        /**
         * 绘制到线条下面
         */
        const val BOTTOM = 2
    }
}

/**
 * 标签绘制的位置
 *
 * @author Created by wanggaowan on 2022/8/5 11:42
 */
open class LabelPosition private constructor() {

    /**
     * 绘制在扇形内部
     */
    open class Inside : LabelPosition() {
        var offsetCenterPercent: Float = 0.6f
            protected set

        /**
         * 距离圆心的偏移百分比
         */
        fun offsetCenterPercent(percent: Float): Inside {
            offsetCenterPercent = percent
            return this
        }
    }

    /**
     * 绘制在扇形外部，绘制在外部时，会多绘制一条指示线。标签绘制在指示线上下或尾部
     */
    open class OutSide : LabelPosition() {
        var labelGravity: Int = LabelGravity.TOP
            protected set
        var lineFactory: LineFactory = object : LineFactory {
            override fun invoke(entity: BasePieEntity): IndicatorLine {
                return IndicatorLine.newInstance()
            }
        }
            private set


        /**
         * 标签绘制位置
         */
        fun labelGravity(@LabelGravity gravity: Int): OutSide {
            labelGravity = gravity
            return this
        }

        /**
         * 标签指示线构造器
         */
        fun lineFactory(factory: LineFactory): OutSide {
            lineFactory = factory
            return this
        }
    }

    companion object {
        /**
         * 绘制在扇形内部
         */
        @JvmStatic
        fun inside(): Inside {
            return Inside()
        }

        /**
         * 绘制在扇形外部，绘制在外部时，会多绘制一条指示线。标签绘制在指示线上下或尾部
         */
        @JvmStatic
        fun outside(): OutSide {
            return OutSide()
        }
    }
}

/**
 * 标签指示线
 */
open class IndicatorLine private constructor() {
    var color: Int = Color.BLACK
        protected set
    var width: Float = 2f.px
        protected set
    var maxLength: Float? = null
        protected set
    var minLength: Float = 0f
        protected set
    var offset: Float = 0f
        protected set
    var drawStartCircle: Boolean = false
        protected set
    var circleRadius: Float = 4f.px
        protected set
    var circleColor: Int = Color.GRAY


    /**
     * 线条颜色
     */
    fun color(color: Int): IndicatorLine {
        this.color = color
        return this
    }

    /**
     * 线条粗细
     */
    fun width(lineWidth: Float): IndicatorLine {
        this.width = lineWidth
        return this
    }

    /**
     * 线条最大长度，不设置则取文本的宽度。设置则文本最大绘制宽度为当前设定值
     */
    fun maxLength(@Px maxWidth: Float?): IndicatorLine {
        this.maxLength = maxWidth
        return this
    }

    /**
     * 线条最小长度
     */
    fun minLength(@Px minWidth: Float): IndicatorLine {
        this.minLength = minWidth
        return this
    }

    /**
     * 线条与饼状图偏移值
     */
    fun offset(@Px offset: Float): IndicatorLine {
        this.offset = offset
        return this
    }

    /**
     * 是否在线条起始处位置一个圆点
     */
    fun drawStartCircle(draw: Boolean): IndicatorLine {
        this.drawStartCircle = draw
        return this
    }

    /**
     * 圆点半径
     */
    fun circleRadius(@Px radius: Float): IndicatorLine {
        this.circleRadius = radius
        return this
    }

    /**
     * 圆点颜色
     */
    fun circleColor(@ColorInt color: Int): IndicatorLine {
        this.circleColor = color
        return this
    }

    companion object {
        @JvmStatic
        fun newInstance(): IndicatorLine {
            return IndicatorLine()
        }
    }
}

/**
 * 标签指示线构建器
 */
typealias LineFactory = (entity: BasePieEntity) -> IndicatorLine

